package com.qing.qingcodegenerate.exception;

import cn.hutool.json.JSONUtil;
import com.qing.qingcodegenerate.common.BaseResponse;
import com.qing.qingcodegenerate.common.ResultUtils;
import io.swagger.v3.oas.annotations.Hidden;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Hidden
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /**
     * 处理方法参数验证异常（MethodArgumentNotValidException）。
     * 当使用 @Valid 注解进行参数验证时，如果参数验证不通过，会抛出该异常。
     *
     * @param e 方法参数验证异常对象
     * @return 返回一个包含错误信息的 BaseResponse 对象，状态码为 400 Bad Request
     */
//    @ExceptionHandler(MethodArgumentNotValidException.class)
//    // 设置响应状态码为 400 Bad Request
//    @ResponseStatus(HttpStatus.BAD_REQUEST)
//    public BaseResponse<?> handleValidException(MethodArgumentNotValidException e) {
//        // 记录错误日志，包含异常信息和异常类型
//        log.error("数据效验出现问题{},异常类型{}", e.getMessage(), e.getClass());
//        // 获取绑定结果，其中包含了所有验证失败的信息
//        BindingResult bindingResult = e.getBindingResult();
//
//
//        // 创建一个 Map 用于存储每个字段的错误信息
//        Map<String, String> errMap = new HashMap<>();
//
//        if(bindingResult.hasErrors()) {
//            FieldError firstError = bindingResult.getFieldErrors().get(0);
//            errMap.put(firstError.getField(), firstError.getDefaultMessage());
//        }
//
////        // 遍历所有验证失败的字段错误信息
////        bindingResult.getFieldErrors().forEach((fieldError) -> {
////            // 将字段名和对应的错误信息存入 Map 中
////            errMap.put(fieldError.getField(), fieldError.getDefaultMessage());
////        });
//        // 返回一个包含错误信息的 BaseResponse 对象，错误码为 PARAMS_ERROR，错误信息为 PARAMS_ERROR 的消息，具体错误信息为 errMap 的字符串形式
//        return new BaseResponse<>(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMessage(), errMap.toString());
//    }
    @ExceptionHandler(BusinessException.class)
    public BaseResponse<?> businessExceptionHandler(BusinessException e) {
        log.error("BusinessException", e);
        // 尝试处理 SSE 请求
        if (handleSseError(e.getCode(), e.getMessage())) {
            return null;
        }
        // 对于普通请求，返回标准 JSON 响应
        return ResultUtils.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(RuntimeException.class)
    public BaseResponse<?> runtimeExceptionHandler(RuntimeException e) {
        log.error("RuntimeException", e);
        // 尝试处理 SSE 请求
        if (handleSseError(ErrorCode.SYSTEM_ERROR.getCode(), "系统错误")) {
            return null;
        }
        return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "系统错误");
    }
    /**
     * 处理SSE请求的错误响应
     *
     * @param errorCode 错误码
     * @param errorMessage 错误信息
     * @return true表示是SSE请求并已处理，false表示不是SSE请求
     */
//     设置响应状态码为 401 Bad Request
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    private boolean handleSseError(int errorCode, String errorMessage) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            return false;
        }
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        // 判断是否是SSE请求（通过Accept头或URL路径）
        String accept = request.getHeader("Accept");
        String uri = request.getRequestURI();
        if ((accept != null && accept.contains("text/event-stream")) ||
                uri.contains("/chat/gen/code")) {
            try {
                // 设置SSE响应头
                response.setContentType("text/event-stream");
                response.setCharacterEncoding("UTF-8");
                response.setHeader("Cache-Control", "no-cache");
                response.setHeader("Connection", "keep-alive");
                // 构造错误消息的SSE格式
                Map<String, Object> errorData = Map.of(
                        "error", true,
                        "code", errorCode,
                        "message", errorMessage
                );
                String errorJson = JSONUtil.toJsonStr(errorData);
                // 发送业务错误事件（避免与标准error事件冲突）
                String sseData = "event: business-error\ndata: " + errorJson + "\n\n";
                response.getWriter().write(sseData);
                response.getWriter().flush();
                // 发送结束事件
                response.getWriter().write("event: done\ndata: {}\n\n");
                response.getWriter().flush();
                // 表示已处理SSE请求
                return true;
            } catch (IOException ioException) {
                log.error("Failed to write SSE error response", ioException);
                // 即使写入失败，也表示这是SSE请求
                return true;
            }
        }
        return false;
    }

}
